<template>
  <t-table-column v-bind="$attrs" class-name="tiny-table-column-edit">
    <!-- 判断slots是否为对象，如果是，并且对象中header也是函数，则渲染进表头插槽中 -->
    <template
      v-if="isFunction(get(slots, 'header', null))"
      v-slot:header="scope"
    >
      <tiny-render
        :template="slots.header"
        :params="[scope.column, scope.$index]"
      ></tiny-render>
    </template>
    <template v-slot:default="scope">
      <template v-if="editable && visible">
        <t-input
          :key="getKey('input', scope)"
          v-model="curValue"
          v-popover:popover
          autofocus
        />
        <t-popover
          ref="popover"
          :key="getKey('popover', scope)"
          placement="right"
          trigger="focus"
        >
          <t-button
            :key="getKey('btn1', scope)"
            type="primary"
            size="mini"
            @click="onConfirm(scope)"
            >确定
          </t-button>
          <t-button
            :key="getKey('btn2', scope)"
            size="mini"
            @click="onCancel(scope)"
          >
            取消
          </t-button>
        </t-popover>
      </template>
      <template v-else>
        <!-- 判断slots是否为一个函数，如果是则使用tiny-render渲染进默认插槽中 -->
        <div class="tiny-table-column-edit__container">
          <tiny-render
            v-if="isFunction(slots)"
            :template="slots"
            :params="[scope.row, scope.column, scope.$index, scope]"
          ></tiny-render>
          <!-- 判断slots是否为对象，如果是，并且对象中default也是函数，则渲染进默认插槽中 -->
          <tiny-render
            v-else-if="isFunction(get(slots, 'default', null))"
            :template="slots.default"
            :params="[scope.row, scope.column, scope.$index, scope]"
          ></tiny-render>
          <span v-else>{{ getValue(scope) }}</span>
          <div
            v-if="editable"
            class="tiny-table-column-edit__tag"
            title="双击单元格进行修改"
            @dblclick="onEdit(scope)"
          >
            &nbsp;
          </div>
        </div>
      </template>
    </template>
  </t-table-column>
</template>

<script>
import TinyTableColumn from "./TinyTableColumn";
import TinyRender from "./TinyRender";

export default {
  name: "TinyTableColumnEdit",
  components: {
    TinyTableColumn,
    TinyRender,
  },
  props: {
    /**
     * @description 表格列插槽
     * @type {Function|Object}
     */
    slots: {
      type: [Function, Object],
      default: null,
    },
    editable: {
      type: Boolean,
      default: false,
    },
    tagPosition: {
      type: String,
      default: "left", // right
    },
		editEvents: {
			type: Object,
			default: () => ({})
		}
  },
  data() {
    return {
      visible: false,
      curValue: "",
      oldValue: "",
    };
  },
  methods: {
    /**
     * @description 判断是否是函数
     * @param {Function} fn
     * @returns {Boolean}
     */
    isFunction(fn) {
      return Object.prototype.toString.call(fn) === "[object Function]";
    },
    /**
     * @description 获取对象的属性
     * @param {Object} object
     * @param {String} path
     * @param {Any} defaultValue
     * @returns {Any}
     */
    get(object, path, defaultValue) {
      // 判断Object是否为Object类型
      if (Object.prototype.toString.call(object) !== "[object Object]") {
        return defaultValue;
      }

      const pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g);
      return (
        pathArray.reduce((acc, key) => acc && acc[key], object) || defaultValue
      );
    },
    getKey(type, scope) {
      return `${type}_${scope.column.id}_${scope.$index}`;
    },
    getValue(scope) {
      const key = scope.column?.property ?? "";

      if (!key) {
        return "";
      }

      // scope.row不是对象时返回空字符串
      if (Object.prototype.toString.call(scope.row) !== "[object Object]") {
        return "";
      }

      return scope.row[key];
    },
    onConfirm(scope) {
			if (this.editEvents?.onConfirm && typeof this.editEvents.onConfirm === 'function') {
				this.editEvents.onConfirm({
					row: scope.row,
					column: scope.column,
					newValue: this.curValue,
					oldValue: this.oldValue,
				});
			}
      this.$set(scope.row, scope.column.property, this.curValue);
      this.visible = false;
    },
    onCancel(scope) {
			if (this.editEvents?.onCancel && typeof this.editEvents.onCancel === 'function') {
				this.editEvents.onCancel({
					row: scope.row,
					column: scope.column,
					newValue: this.curValue,
					oldValue: this.oldValue,
				});

			}
      this.$set(scope.row, scope.column.property, this.oldValue);
      this.visible = false;
    },
    /**
     *
     * @param {Object} scope
     * @param {Object} scope.column
     * @param {string} scope.column.property
     * @param {Object} scope.row
     * @param {numebr} scope.$index
     */
    onEdit(scope) {
      const curVal = scope.row[scope.column.property] ?? "";
      this.curValue = curVal;
      this.oldValue = curVal;
      this.visible = true;
    },
  },
};
</script>

<style lang="less">
.t-table__body {
  .tiny-table-column-edit {
    &.t-table__cell {
      padding: 0;
      position: relative;
      overflow: hidden;
    }

    &__container {
      width: 100%;
      min-height: 36px;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    &__tag {
      width: 0;
      height: 0;
      border-top: 12px solid #439be6;
      border-right: 12px solid transparent;
      border-left: 12px solid transparent;
      transform: rotate(135deg);
      position: absolute;
      left: -12px;
      top: -2px;
    }
  }
}
</style>
